package main

import (
	"fmt"
	"strconv"
	"sync"
	"time"
)

func producer1(wg *sync.WaitGroup, c chan int) {
	fmt.Printf("producer: waiting for 3 seconds ...\n")
	time.Sleep(time.Second * 3)
	v := 42
	fmt.Printf("producer: put value: %d\n", v)
	c <- v

	fmt.Printf("producer: waiting for 1 seconds ...\n")
	time.Sleep(time.Second * 1)
	v = 52
	fmt.Printf("producer: put value: %d\n", v)
	c <- v
	wg.Done()
}

func consumer1(name string, wg *sync.WaitGroup, c chan int) {
	fmt.Printf("consumer(%s): waiting for value ...\n", name)
	v := <-c
	fmt.Printf("consumer(%s): get value: %d\n", name, v)
	wg.Done()
}

func singleProvider() {
	c := make(chan int)
	wg := sync.WaitGroup{}
	wg.Add(3)
	go producer1(&wg, c)
	go consumer1("1", &wg, c)
	go consumer1("2", &wg, c)
	wg.Wait()
}

func consumer2(name string, wg *sync.WaitGroup, c chan int) {
	for i := 0; i < 5; i++ {
		fmt.Printf("consumer(%s): waiting 1 second ...\n", name)
		time.Sleep(time.Second * 1)
		v := <-c
		fmt.Printf("consumer(%s): get value: %d\n", name, v)
	}
	wg.Done()
}

func producer2(name string, wg *sync.WaitGroup, c chan int) {
	fmt.Printf("producer(%s): waiting for 3 seconds ...\n", name)
	time.Sleep(time.Second * 3)
	i, _ := strconv.Atoi(name)
	v := 100 + i
	fmt.Printf("producer(%s): put value: %d\n", name, v)
	c <- v
	wg.Done()
}

func multiProvider() {
	c := make(chan int, 2)
	wg := sync.WaitGroup{}
	wg.Add(12)
	for i := 0; i < 10; i++ {
		go producer2(strconv.Itoa(i), &wg, c)
	}
	go consumer2("1", &wg, c)
	go consumer2("2", &wg, c)
	wg.Wait()
}

func main() {
	// singleProvider()
	multiProvider()
}
